package r3.rpc.protocol.codec;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;
import r3.rpc.RpcRequest;
import r3.rpc.RpcResponse;
import r3.rpc.protocol.serialization.Serialization;

import java.util.List;

/**
 * RpcDecoder
 *
 * @author zhoufn
 * @create 2017-12-25 11:16
 **/
@Slf4j
public class RpcDecoder extends ByteToMessageDecoder{

    private Serialization serialization;

    private Class<?> clazz;

    public RpcDecoder(Serialization serialization,Class<?> clazz){
        this.serialization = serialization;
        this.clazz = clazz;
    }

    /**
     * Decode the from one {@link ByteBuf} to an other. This method will be called till either the input
     * {@link ByteBuf} has nothing to read when return from this method or till nothing was read from the input
     * {@link ByteBuf}.
     *
     * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to
     * @param in  the {@link ByteBuf} from which to read data
     * @param out the {@link List} to which decoded messages should be added
     * @throws Exception is thrown if an error accour
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if (in.readableBytes() < 4) {
            return;
        }

        in.markReaderIndex();

        int length = in.readInt();
        if (length < 0) {
            ctx.close();
        }
        if (in.readableBytes() < length) {
            in.resetReaderIndex();
            return;
        }
        //解码
        byte[] body = new byte[length];
        in.readBytes(body);
        Object message = serialization.deserialize(body, this.clazz);
        out.add(message);
    }
}
